package com.qf.smartdevice.service.impl;

import com.alibaba.druid.util.StringUtils;
import com.github.pagehelper.PageInfo;
import com.qf.smartdevice.cache.CategoriesCache;
import com.qf.smartdevice.constans.ResultCode;
import com.qf.smartdevice.event.CategoryCacheChangeEvent;
import com.qf.smartdevice.exceptions.AddDateException;
import com.qf.smartdevice.mapper.CategoryMapper;
import com.qf.smartdevice.pojo.Categories;
import com.qf.smartdevice.service.ICategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional
public class CategoryServiceImpl implements ICategoryService {
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private CategoriesCache categoriesCache;
    @Autowired
    private ApplicationContext context;
    @Autowired
    private CategoryCacheChangeEvent event;

    @Override
    @Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
    public PageInfo<Categories> findAllCategoriesByPage(int page, int limit, String categoryname, Long status) {

        PageInfo<Categories> pageInfo = null;

        List<Categories> categoriesList = categoriesCache.getAllDate();

        //遍历集合,判断每条数据是不是符合我们的查询条件
        List<Categories> realCategoriesList = categoriesList.stream().filter(categories -> {
            boolean isFetchName = true;
            boolean isFetchStatus = true;
            String categoryname1 = categories.getCategoryname();//获取对象上面的分类名,用于和名字进行判断
            Long status1 = categories.getStatus();//获取对象上面的状态
            if (!StringUtils.isEmpty(categoryname)){
                //代表了分类的名字
                isFetchName = categoryname1.contains(categoryname);//判断分类的名字中是否包含传递的名字
            }
            if (status!=null&&-100!=status){//如果传递了状态并且不是默认的无状态
                //判断对象的状态和查询的状态是否一致
                isFetchStatus = status == status1;
            }

            return isFetchName &&  isFetchStatus;// stream 的 filter 要求返回一个 boolean,此时返回的就是是否匹配传递的用户名和状态条件
        }).collect(Collectors.toList());

        int last_index = limit;//为了防止第一页没有数据,默认先写上  limit
        if (page*limit >= realCategoriesList.size()){//为了防止出现在切割集合的时候出现数组越界
            last_index = realCategoriesList.size();//如果超出了总长度,则最后的一个切割下标就是总长度
        }else {
            last_index = page*limit;//在不超出范围的情况下就是当前页*每页的数量
        }

        if ((page - 1)*limit >= realCategoriesList.size()){
            //起点超出查询范围了,直接返回空数据
            pageInfo=new PageInfo<>();
            return pageInfo;
        }
        //切割集合,上面的代码都是怕越界而做的判断
        List<Categories> subList = realCategoriesList.subList((page - 1) * limit, last_index);
        pageInfo = new PageInfo<>(subList);
        pageInfo.setTotal(realCategoriesList.size());//设置总长度为符合条件的集合长度
        return pageInfo;
    }

    @Override
    public void addCategory(Categories categories) {
        if (categories==null||categories.isNull()){
            throw new AddDateException("数据不能为空", ResultCode.DATA_NOT_EXIST);
        }
        categoryMapper.addCategoy(categories);
        //更新缓存,如果在这里做缓存操作,出现异常会导致事务回滚,添加失败,更新缓存不应该影响添加数据
        //即使是更新缓存失败,也不应该回滚数据,也就是说这是两个完全独立的操作
        context.publishEvent(event);//发送事件,解耦
    }
}
